<template>
	<transition
		:css="false"
		@before-enter="$_lexmis_beforeEnter"
		@enter="$_lexmis_enter"
		@leave="$_lexmis_leave"
		@after-leave="$_lexmis_afterLeave">
		<div
			v-if="value"
			class="lexmis-Modal"
			:style="{zIndex}">
			<div
				class="lexmis_dialog"
				:style="[style,offset]">
				<div
					v-if="head"
					class="lexmis_head">
					<div
						class="lexmis_title"
						:style="{paddingRight:closable?null:'16px'}"
						@mousedown="$_lexmis_startMove">
						<slot name="title">{{title}}</slot>
					</div>
					<div
						v-if="closable"
						class="lexmis_close">
						<Icon name="close" @click="close(false)"/>
					</div>
					<QResizeObserver :debounce="100" @resize="$_lexmis_resizeHead"/>
				</div>
				<div class="lexmis_body">
					<BothScrollArea
						ref="scroll"
						v-slot="{width,height}"
						:full-width="fullWidth"
						@resize="$_lexmis_resizeModal"
						@inner-resize="$_lexmis_resizeContent">
						<slot
							:width="width"
							:height="height"></slot>
					</BothScrollArea>
					<QInnerLoading
						:showing="loading"
						class="lexmis_loading">
						<slot name="spinner"><Spinner/></slot>
					</QInnerLoading>
				</div>
				<div
					v-if="foot"
					class="lexmis_foot">
					<slot name="foot">
						<Button :rounded="$baseui_theme=='fk'" type="primary" :loading="loadingConfirm" @click="confirm">{{confirmText}}</Button>
						<Button :rounded="$baseui_theme=='fk'" :type="closeType" @click="close(true)">{{closeText}}</Button>
					</slot>
					<QResizeObserver :debounce="100" @resize="$_lexmis_resizeFoot"/>
				</div>
			</div>
		</div>
	</transition>
</template>

<script>
import Button from '../button';
import Icon from '../icon';
import BothScrollArea from '../both-scroll-area';
import Spinner from '../spinner';
import {QInnerLoading,QResizeObserver} from 'quasar';
import {throttle} from 'lodash';
import {convertCssLength} from '../../../util/common';

let curZIndex=10000;
/**
 * @author 唐国雄
 * 弹窗
 * 属性----------------------
 * v-model			是否显示
 * :full-width		100%宽度
 * :width			宽度,支持带单位和不带单位
 * :height			高度,支持带单位和不带单位,不设置表示根据内容高度
 * :title			标题
 * :h-gap			水平最小预留长度
 * :v-gap			垂直最小预留长度
 * :before-close	关闭前处理器,支持返回promise,返回true表示禁止关闭
 * :head			是否有标题
 * :closable		是否有关闭按钮
 * :foot			是否有页脚
 * :confirm-text	确定按钮文字
 * :close-text		取消按钮文字
 * :loading			加载状态
 * :loading-confirm	确定按钮加载状态
 * 事件----------------------
 * @confirm		点击确认的事件
 * @close		点击关闭时的事件,Boolean是否是底部按钮关闭
 * @resize		模态框body大小改变事件,{width:number,height:number}
 * @show		开始显示
 * @shown		显示动画完毕
 * @hide		开始隐藏
 * @hidden		隐藏动画完毕
 * 插槽----------------------
 * #default		body内容,{width:number,height:number}
 * #title		自定义标题
 * #foot		自定义页脚
 * #spinner		加载中图标
 * 方法----------------------
 * confirm()		模拟确定
 * close(bottom)	模拟关闭,bottom表示是否是底部关闭按钮
 * 引用----------------------
 * scroll		BothScrollArea组件
 */
export default {
	name:'Modal',
	components:{
		Icon,
		Button,
		BothScrollArea,
		QResizeObserver,
		QInnerLoading,
		Spinner,
	},
	props:{
		//100%宽度
		fullWidth:Boolean,
		//宽度
		width:{
			type:[Number,String],
			default:420
		},
		//高度
		height:{
			type:[Number,String],
			default:0
		},
		//标题
		title:String,
		//显示状态
		value:Boolean,
		//水平最小预留长度
		hGap:{
			type:Number,
			default:50
		},
		//垂直最小预留长度
		vGap:{
			type:Number,
			default:50
		},
		//关闭前处理器,支持返回promise,返回true表示禁止关闭
		beforeClose:Function,
		//是否有标题
		head:{
			type:Boolean,
			default:true
		},
		//是否有关闭按钮
		closable:{
			type:Boolean,
			default:true
		},
		//是否有页脚
		foot:{
			type:Boolean,
			default:true
		},
		//确定按钮文字
		confirmText:{
			type:String,
			default:'确定'
		},
		//取消按钮文字
		closeText:{
			type:String,
			default:'取消'
		},
		//加载状态
		loading:Boolean,
		//确定按钮加载状态
		loadingConfirm:Boolean,
	},
	data(){
		return {
			//遮罩层宽度
			maskWidth:window.innerWidth,
			//遮罩层高度
			maskHeight:window.innerHeight,
			//弹窗宽度
			realWidth:0,
			//实际内容高度
			contentHeight:0,
			//body容器高度
			bodyHeight:0,
			//标题高度
			headHeight:0,
			//页脚高度
			footHeight:0,
			//x坐标
			x:0,
			//y坐标
			y:0,
			//层级
			zIndex:0,
		};
	},
	computed:{
		//应用到模态框的样式
		style(){
			let height=0;
			if(this.head){
				height+=this.headHeight;
			}
			if(this.foot){
				height+=this.footHeight;
			}
			return {
				maxWidth:this.maskWidth-this.hGap+'px',
				maxHeight:this.maskHeight-this.hGap+'px',
				width:convertCssLength(this.width),
				height:this.height?convertCssLength(this.height):this.contentHeight+height+'px',
			};
		},
		//真实高度
		realHeight(){
			let height=0;
			if(this.head){
				height+=this.headHeight;
			}
			if(this.foot){
				height+=this.footHeight;
			}
			return this.bodyHeight+height;
		},
		//初始left
		initLeft(){
			return Math.floor((this.maskWidth-this.realWidth)/2);
		},
		//初始top
		initTop(){
			return Math.floor((this.maskHeight-this.realHeight)/2);
		},
		//偏移样式
		offset(){
			return {
				left:this.x+this.initLeft+'px',
				top:this.y+this.initTop+'px',
			};
		},
		//关闭按钮类型(不同主题不一样)
		closeType(){
			if(this.$baseui_theme==='fk'){
				return 'error';
			}
			return 'default';
		},
	},
	watch:{
		value:{
			handler(val){
				if(val){
					this.$emit('show');
					this.zIndex=curZIndex++;
				}else{
					this.$emit('hide');
					--curZIndex;
				}
			},
		},
	},
	created(){
		if(this.value){
			this.zIndex=curZIndex++;
		}
		//拖拽节流
		this.$_lexmis_moving2=throttle(this.$_lexmis_moving,16,{trailing:false});
	},
	mounted(){
		document.body.appendChild(this.$el);
	},
	beforeDestroy(){
		this.$el.remove();
	},
	methods:{
		//进入动画前
		$_lexmis_beforeEnter(el){
			this.x=0;
			this.y=0;
			this.maskWidth=window.innerWidth;
			this.maskHeight=window.innerHeight;
		},
		//进入动画
		$_lexmis_enter(el,done){
			const callback=(e) => {
				if(e.target===el){
					el.classList.remove('v-enter-active');
					done();
					this.$emit('shown');
					el.removeEventListener('animationend',callback);
				}
			};
			el.addEventListener('animationend',callback);
			if(this.height){
				el.classList.add('v-enter-active');
			}else{
				el.style.visibility='hidden';
				this.$once('resize',function(){
					el.style.visibility='visible';
					el.classList.add('v-enter-active');
				});
			}
		},
		//离开动画
		$_lexmis_leave(el,done){
			const callback=(e) => {
				if(e.target===el){
					el.classList.remove('v-leave-active');
					done();
					this.$emit('hidden');
					el.removeEventListener('animationend',callback);
				}
			};
			el.addEventListener('animationend',callback);
			el.classList.add('v-leave-active');
		},
		//离开动画后
		$_lexmis_afterLeave(){
			this.contentHeight=0;
		},
		//开始拖拽
		$_lexmis_startMove({clientX,clientY}){
			this.startX=clientX;
			this.startY=clientY;
			window.addEventListener('mousemove',this.$_lexmis_moving2,{passive:true});
			window.addEventListener('mouseup',this.$_lexmis_endMove,{passive:true});
		},
		//拖拽中
		$_lexmis_moving({clientX,clientY}){
			this.x=Math.max(-this.initLeft,Math.min(this.x+clientX-this.startX,this.maskWidth-this.initLeft-this.realWidth));
			this.y=Math.max(-this.initTop,Math.min(this.y+clientY-this.startY,this.maskHeight-this.initTop-this.headHeight));
			this.startX=clientX;
			this.startY=clientY;
		},
		//结束拖拽
		$_lexmis_endMove({clientX,clientY}){
			window.removeEventListener('mousemove',this.$_lexmis_moving2,{passive:true});
			window.removeEventListener('mouseup',this.$_lexmis_endMove,{passive:true});
		},
		//模态框body大小变化
		$_lexmis_resizeModal(size){
			this.$emit('resize',size);
			this.realWidth=size.width;
			this.bodyHeight=size.height;
		},
		//实际内容大小变化
		$_lexmis_resizeContent({height}){
			this.contentHeight=height;
		},
		//标题大小变化
		$_lexmis_resizeHead({height}){
			this.headHeight=height;
		},
		//页脚大小变化
		$_lexmis_resizeFoot({height}){
			this.footHeight=height;
		},
		//确定
		confirm(){
			this.$emit('confirm');
		},
		//关闭
		close(bottom){
			const beforeClose=this.beforeClose;
			Promise.resolve(beforeClose&&beforeClose()).then((prevent) => {
				if(!prevent){
					this.$emit('close',bottom);
					this.$emit('input',false);
				}
			});
		},
	}
};
</script>
